package wechat

import (
	"bytes"
	"errors"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"strings"
	"time"

	"fmt"

	jsoniter "github.com/json-iterator/go"
)

type getUnlimitedRequestParams struct {
	Scene string `json:"scene"`
	Page  string `json:"page"`
	//width       int    `json:"width"`
	//width       int    `json:"width"`
}

type errresp struct {
	Errcode int    `json:"errcode"`
	Errmsg  string `json:"errmsg"`
}

type AccessToken struct {
	AccessToken string `json:"access_token"`
	ExpiresIn   int    `json:"expires_in"`
	Errcode     int    `json:"errcode"`
	Errmsg      string `json:"errmsg"`
}

//GetUnlimited 获取产品小程序码
func (w *Wx) GetUnlimited(page, scene, savepath string) (err error) {
	var gurp getUnlimitedRequestParams
	gurp.Page = page
	gurp.Scene = scene
	requsetbyte, err := jsoniter.Marshal(gurp)
	if err != nil {
		return
	}
	accesstoken, err := w.GetAccessTokenMiniapp()
	if err != nil {
		return
	}
	var b bytes.Buffer
	b.Write(requsetbyte)
	resp, err := http.Post(getUnlimitedUrl+"?access_token="+accesstoken, "application/json", &b)
	if err != nil {
		return
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return
	}
	var er errresp
	_ = jsoniter.Unmarshal(body, &er)
	if er.Errcode == 0 {
		createDir(savepath)
		out, _ := os.Create(savepath)
		_, err = io.Copy(out, bytes.NewReader(body))
	} else {
		err = errors.New(fmt.Sprintf("ErrCode : %v,ErrMsg : %s", er.Errcode, er.Errmsg))
	}
	return
}

func createDir(path string) {
	paths := strings.Split(path, "/")
	dirpaths := strings.Join(paths[:len(paths)-1], "/")
	if !exist(dirpaths) {
		_ = os.MkdirAll(dirpaths, 0777)
	}
}

func (w *Wx) GetAccessTokenMiniapp() (accesstoken string, err error) {
	if w.miniappAccesstoken.Cretetime+expire < time.Now().Unix() {
		err = w.flushAccessTokenMiniapp()
		if err != nil {
			return
		}
	}
	accesstoken = w.miniappAccesstoken.Accesstoken
	return
}

func (w *Wx) flushAccessTokenMiniapp() (err error) {
	w.m.Lock()
	defer w.m.Unlock()
	resq, err := http.Get(fmt.Sprintf(getAccesstokenMiniappUrl, w.config.MiniAppid, w.config.MiniAppsecret))
	if err != nil {
		return
	}
	defer resq.Body.Close()
	body, err := ioutil.ReadAll(resq.Body)
	if err != nil {
		return
	}
	var at AccessToken
	err = jsoniter.Unmarshal(body, &at)
	if err != nil {
		return
	}
	if at.Errcode > 0 {
		err = errors.New(at.Errmsg)
		return
	}
	//写入文件
	w.miniappAccesstoken.Accesstoken = at.AccessToken
	w.miniappAccesstoken.Cretetime = time.Now().Unix()
	fb, err := jsoniter.Marshal(w.miniappAccesstoken)
	if err != nil {
		return
	}
	err = ioutil.WriteFile(miniappjsonpath, fb, 0777)
	return
}

type SubscribeMessage struct {
	Openid           string                 `json:"touser"`
	TemplateId       string                 `json:"template_id"`
	Page             string                 `json:"page"`
	Data             map[string]interface{} `json:"data"`
	MiniprogramState string                 `json:"miniprogram_state"`
	Lang             string                 `json:"lang"`
}

func (w *Wx) SubscribeMessageSend(sb SubscribeMessage) (err error) {
	requsetbyte, err := jsoniter.Marshal(sb)
	var b bytes.Buffer
	b.Write(requsetbyte)
	accesstoken, err := w.GetAccessTokenMiniapp()
	if err != nil {
		return
	}
	resp, err := http.Post(subscribeMessageSend+"?access_token="+accesstoken, "application/json", &b)
	if err != nil {
		return
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return
	}
	var er errresp
	err = jsoniter.Unmarshal(body, &er)
	if err != nil {
		return
	}
	if er.Errcode != 0 {
		err = errors.New(fmt.Sprintf("ErrCode : %v,ErrMsg : %s", er.Errcode, er.Errmsg))
	}
	return
}
